package org.rmm.service;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.rmm.db.Repository;
import org.rmm.model.Customer;
import org.rmm.model.Item;
import org.rmm.model.Order;
import org.rmm.representation.OrderRepresentation;

/**
 * WebAPI using URI tunneling, Overloading GET. 
 * /GetOrders
 * /SubmitOrder?orderId={orderId}&orderCurrency={orderCurrency}&orderStatus={orderStatus}&customerName={customerMail}&customerEmail={customerEmail}
 * /GetOrderDetails?orderId={orderId}
 * /UpdateOrder?orderId={orderId}&orderCurrency={orderCurrency}&orderStatus={orderStatus}&customerName={customerMail}&customerEmail={customerEmail}
 * /AddOrderItem?orderId={orderId}&itemId={itemId}&itemPrice={itemPrice}&itemQuantity={itemQuantity}
 * /CancelOrder?orderId={orderId}
 *
 * 
 * @author jvelilla
 * 
 */

public class OrderManagementService extends HttpServlet {

	private static final String APPLICATION_JSON = "application/json";
	private static final Logger LOG = Logger
			.getLogger(OrderManagementService.class);
	private static final long serialVersionUID = 1L;

	public void doGet(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {
		String qString = req.getQueryString();
		String pathInfo = req.getPathInfo();

		if ("/SubmitOrder".equals(pathInfo)) {
			this.submitOrder(qString, res);
		} else if ("/GetOrders".equals(pathInfo)) {
			this.getOrders(res);
		} else if ("/GetOrderDetails".equals(pathInfo)) {
			this.getOrderDetails(qString, res);
		} else if ("/UpdateOrder".equals(pathInfo)) {
			this.updateOrder(qString, res);
		} else if ("/AddOrderItem".equals(pathInfo)) {
			this.addOrderItem(qString, res);
		} else if ("/CancelOrder".equals(pathInfo)) {
			this.cancelOrder(qString, res);
		} else {
			res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
		}

	}

	private void cancelOrder(String qString, HttpServletResponse res) {
		try {
			String[] param = qString.split("=");
			Repository.INSTANCE.removeOrder(param[1]);
			res.setStatus(HttpServletResponse.SC_NO_CONTENT);
		} catch (Exception e) {
			res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		}
	}

	private void addOrderItem(String qString, HttpServletResponse res) {
		try {
			Map<String, String> qValues = new HashMap<String, String>(3);
			String[] split = qString.split("&");
			LOG.info(split);
			for (String qparam : split) {
				String[] q = qparam.split("=");
				qValues.put(q[0], q[1]);
			}

			Order o = Repository.INSTANCE
					.retrieveOrder(qValues.get("orderId"));
			Item i = new Item();
			i.setId(qValues.get("itemId"));
			i.setPrice(Double.valueOf(qValues.get("itemPrice")));
			i.setQuantity(Integer.valueOf(qValues.get("itemQuantity")));
			o.addItem(i);
			Repository.INSTANCE.updateOrder(o);
			res.setStatus(HttpServletResponse.SC_NO_CONTENT);
		} catch (Exception e) {
			res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		}

	}

	private void updateOrder(String qString, HttpServletResponse res) {
		try {
			Order o = new Order();
			Customer c = new Customer();
			Map<String, String> qValues = new HashMap<String, String>(10);

			String[] split = qString.split("&");
			LOG.info(split);
			for (String qparam : split) {
				String[] q = qparam.split("=");
				qValues.put(q[0], q[1]);
			}
			c.setEmail(qValues.get("customerEmail"));
			c.setName(qValues.get("customerName"));
			o.setId(qValues.get("orderId"));
			o.setCurrency(qValues.get("orderCurrency"));
			o.setStatus(qValues.get("orderStatus"));
			o.setPlaced(new Boolean(qValues.get("orderPlaced")));
			o.setCustomer(c);
			res.setContentType(APPLICATION_JSON);
			res.setStatus(HttpServletResponse.SC_OK);
			Repository.INSTANCE.updateOrder(o);
			PrintWriter out = res.getWriter();
			out.print(new OrderRepresentation().writeOrderRepresentation(Repository.INSTANCE.retrieveOrder(o.getId())));
		} catch (Exception e) {
			res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		}

	}

	private void getOrders(HttpServletResponse res) {
		try {
			PrintWriter out = res.getWriter();
			Collection<Order> orders = Repository.INSTANCE.getOrders();
			res.setContentType(APPLICATION_JSON);
			String response = "[";
			for (Order order : orders) {
				response = response + new OrderRepresentation().writeOrderRepresentation(order);
			}
			response = response + "]";
			out.print(response);
			res.setStatus(HttpServletResponse.SC_OK);
		} catch (Exception e) {
			res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		}
	}

	private void getOrderDetails(String qString, HttpServletResponse res) {
		try {
			String[] param = qString.split("=");
			Order o = Repository.INSTANCE.retrieveOrder(param[1]);
			res.setContentType(APPLICATION_JSON);
			PrintWriter out = res.getWriter();
			out.print(new OrderRepresentation().writeOrderRepresentation(o));
			res.setStatus(HttpServletResponse.SC_OK);
		} catch (Exception e) {
			res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		}
	}

	private void submitOrder(String qString, HttpServletResponse res) {
		try {
			Order o = new Order();
			Customer c = new Customer();
			Map<String, String> qValues = new HashMap<String, String>(10);

			String[] split = qString.split("&");
			LOG.info(split);
			for (String qparam : split) {
				String[] q = qparam.split("=");
				qValues.put(q[0], q[1]);
			}
			c.setEmail(qValues.get("customerEmail"));
			c.setName(qValues.get("customerName"));
			o.setId(qValues.get("orderId"));
			o.setCurrency(qValues.get("orderCurrency"));
			o.setStatus(qValues.get("orderStatus"));
			o.setPlaced(new Boolean(qValues.get("orderPlaced")));
			o.setCustomer(c);
			Repository.INSTANCE.addOrder(o);
			res.setContentType(APPLICATION_JSON);
			PrintWriter out = res.getWriter();
			out.print(new OrderRepresentation().writeOrderRepresentation(Repository.INSTANCE.retrieveOrder(o.getId())));
			res.setStatus(HttpServletResponse.SC_CREATED);
		} catch (Exception e) {
			res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		}
	}

}
